﻿// <copyright file="LuminositySlider.cs" company="Oleg V. Polikarpotchkin">
// Copyright © 2009 Oleg V. Polikarpotchkin. All Right Reserved
// </copyright>
// <author>Oleg V. Polikarpotchkin</author>
// <email>ov-p@yandex.ru</email>
// <date>2009-06-05</date>
// <summary>OpenWPFChart library.
// ColorPickerControls. LuminositySlider provides for the Color Luminosity selection.</summary>
// <revision>$Id$</revision>

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace OpenWPFChart.Helpers.ChooseColorDialog
{
	/// <summary>
	/// Provides for the Color Luminosity selection.
	/// </summary>
	public class LuminositySlider : Slider
	{
		/// <summary>
		/// Initializes the <see cref="LuminositySlider"/> class.
		/// </summary>
		static LuminositySlider()
		{
			DefaultStyleKeyProperty.OverrideMetadata(typeof(LuminositySlider)
				, new FrameworkPropertyMetadata(typeof(LuminositySlider)));

			IsDirectionReversedProperty.OverrideMetadata(typeof(LuminositySlider)
				, new FrameworkPropertyMetadata(IsDirectionReversedChanged));
		}

		/// <summary>
		/// Updates the current position of the <see cref="T:System.Windows.Controls.Slider"/> 
		/// when the <see cref="P:System.Windows.Controls.Primitives.RangeBase.Value"/> 
		/// property changes.
		/// </summary>
		/// <param name="oldValue">The old 
		/// <see cref="P:System.Windows.Controls.Primitives.RangeBase.Value"/> of the 
		/// <see cref="T:System.Windows.Controls.Slider"/>.</param>
		/// <param name="newValue">The new 
		/// <see cref="P:System.Windows.Controls.Primitives.RangeBase.Value"/> of the 
		/// <see cref="T:System.Windows.Controls.Slider"/>.</param>
		protected override void OnValueChanged(double oldValue, double newValue)
		{
			base.OnValueChanged(oldValue, newValue);
			UpdateSelectedColor();
		}
		/// <summary>
		/// Responds to a change in the value of the 
		/// <see cref="P:System.Windows.Controls.Primitives.RangeBase.Maximum"/> property.
		/// </summary>
		/// <param name="oldMaximum">The old value of the 
		/// <see cref="P:System.Windows.Controls.Primitives.RangeBase.Maximum"/> property.</param>
		/// <param name="newMaximum">The new value of the 
		/// <see cref="P:System.Windows.Controls.Primitives.RangeBase.Maximum"/> property.</param>
		protected override void OnMaximumChanged(double oldMaximum, double newMaximum)
		{
			base.OnMaximumChanged(oldMaximum, newMaximum);
			UpdateSelectedColor();
		}
		/// <summary>
		/// Responds to a change in the value of the 
		/// <see cref="P:System.Windows.Controls.Primitives.RangeBase.Minimum"/> property.
		/// </summary>
		/// <param name="oldMinimum">The old value of the 
		/// <see cref="P:System.Windows.Controls.Primitives.RangeBase.Minimum"/> property.</param>
		/// <param name="newMinimum">The new value of the 
		/// <see cref="P:System.Windows.Controls.Primitives.RangeBase.Minimum"/> property.</param>
		protected override void OnMinimumChanged(double oldMinimum, double newMinimum)
		{
			base.OnMinimumChanged(oldMinimum, newMinimum);
			UpdateSelectedColor();
		}

		/// <summary>
		/// IsDirectionReversed property changed event handler.
		/// </summary>
		/// <param name="d">The d.</param>
		/// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> 
		/// instance containing the event data.</param>
		static void IsDirectionReversedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			LuminositySlider ths = d as LuminositySlider;
			if (ths == null)
				return;
			ths.UpdateSelectedColor();
		}

		#region BaseColor
		/// <summary>
		/// BaseColor backing DependencyProperty.
		/// </summary>
		private static readonly DependencyProperty BaseColorProperty
			= DependencyProperty.Register("BaseColor", typeof(Color), typeof(LuminositySlider)
			, new FrameworkPropertyMetadata(Colors.Transparent
				, FrameworkPropertyMetadataOptions.AffectsRender
				, BaseColorChanged));
		/// <summary>
		/// Gets or sets the base color.
		/// </summary>
		/// <value>The color instance.</value>
		public Color BaseColor
		{
			get { return (Color)GetValue(BaseColorProperty); }
			set { SetValue(BaseColorProperty, value); }
		}
		/// <summary>
		/// BaseColor property changed event handler.
		/// </summary>
		/// <param name="d">The d.</param>
		/// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> 
		/// instance containing the event data.</param>
		static void BaseColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			LuminositySlider ths = d as LuminositySlider;
			if (ths == null)
				return;
			ths.UpdateSelectedColor();
		}
		#endregion BaseColor

		#region SelectedColor
		/// <summary>
		/// SelectedColor backing DependencyProperty.
		/// </summary>
		private static readonly DependencyPropertyKey SelectedColorPropertyKey
			= DependencyProperty.RegisterReadOnly("SelectedColor", typeof(Color), typeof(LuminositySlider),
				new FrameworkPropertyMetadata(Colors.Transparent
					, FrameworkPropertyMetadataOptions.AffectsRender));
		/// <summary>
		/// Gets the selected color.
		/// </summary>
		/// <value>The color selected.</value>
		public Color SelectedColor
		{
			get { return (Color)GetValue(SelectedColorPropertyKey.DependencyProperty); }
			private set { SetValue(SelectedColorPropertyKey, value); }
		}

		/// <summary>
		/// Coerces the Slider Value to Color.
		/// </summary>
		/// <remarks>
		/// Calculates the Color value according to the Slider Value 
		/// and sets the SelectedColor property.
		/// </remarks>
		void UpdateSelectedColor()
		{
			double v = (Value - Minimum) / (Maximum - Minimum);
			Debug.Assert(v >= 0.0, "v >= 0.0");
			Debug.Assert(v <= 1.0, "v <= 1.0");

			HSL hsl = new HSL(BaseColor);
			hsl.Luminance = v;
			Color clr = (Color)hsl;
			SelectedColor = clr;
			RaiseEvent(new SelectedColorChangedEventArgs(clr, SelectedColorChangedEvent, this));
		}
		#endregion SelectedColor

		#region SelectedColorChangedEvent
		/// <summary>
		/// SelectedColorChangedEvent backing RoutedEvent.
		/// </summary>
		public static readonly RoutedEvent SelectedColorChangedEvent 
			= EventManager.RegisterRoutedEvent("SelectedColorChanged", RoutingStrategy.Bubble
				, typeof(SelectedColorChangedEventHandler), typeof(LuminositySlider));
		/// <summary>
		/// SelectedColorChangedEvent accessors.
		/// </summary>
		public event SelectedColorChangedEventHandler SelectedColorChanged
		{
			add { AddHandler(SelectedColorChangedEvent, value); }
			remove { RemoveHandler(SelectedColorChangedEvent, value); }
		}
		#endregion SelectedColorChangedEvent
	}
}
